package com.xbongbong.pro.message.listener;


import com.alibaba.dingtalk.openapi.exception.OApiException;
import com.alibaba.dingtalk.openapi.helper.AuthHelper;
import com.alibaba.dingtalk.openapi.helper.Env;
import com.alibaba.dingtalk.openapi.helper.MessageHelper;
import com.alibaba.dingtalk.openapi.message.AbstractMessage;
import com.alibaba.dingtalk.openapi.message.LightAppMessageDelivery;
import com.alibaba.dingtalk.openapi.newmessage.entity.OA;
import com.alibaba.dingtalk.openapi.newmessage.entity.template.TemplateMessage;
import com.alibaba.dingtalk.openapi.newmessage.helper.CorpConversationHelper;
import com.alibaba.dingtalk.openapi.newmessage.helper.TemplateMessageTransferHelper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.message.domain.entity.PushEntity;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.coolapp.pojo.dto.CoolAppSendRemindTopCardDTO;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.enums.PushTypeLevelEnum;
import com.xbongbong.pro.message.feign.CoolAppFeignClient;
import com.xbongbong.pro.message.model.PushModel;
import com.xbongbong.pro.message.service.MessageNewService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 消息轮询推送
 * @author 魏荣杰
 * @date 2019/2/22 15:32
 * @since v1.0
 * @version v1.0
 */
@WebListener
public class SysContextListener implements ServletContextListener {
	private static final Logger LOG = LoggerFactory.getLogger(SysContextListener.class);

	private MessageNewService messageNewService;
	private PushModel pushModel;
	private UserModel userModel;
	private AuthHelper authHelper;
	private TemplateMessageTransferHelper templateMessageTransferHelper;
	@Resource
	private CoolAppFeignClient coolAppFeignClient;

	private static ScheduledExecutorService executorLoop = null;
	/**
	 * sfa推送
	 */
	private static ScheduledExecutorService executorLoop1 = null;
	/**
	 * 客户推送
	 */
	private static ScheduledExecutorService executorLoop2 = null;
	/**
	 * level=1的推送,level看 PushTypeLevelEnum
	 */
	private static ScheduledExecutorService executorLoop3 = null;
	/**
	 * level=2的推送
	 */
	private static ScheduledExecutorService executorLoop4 = null;
	/**
	 * level=3的推送
	 */
	private static ScheduledExecutorService executorLoop5 = null;
	/**
	 * 退回公海池推送
	 */
	private static ScheduledExecutorService executorLoop6 = null;

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		ServletContext context = sce.getServletContext();
		ApplicationContext ctx = WebApplicationContextUtils
				.getWebApplicationContext(context);
		pushModel = (PushModel) ctx.getBean("pushModel");
		messageNewService = (MessageNewService) ctx.getBean("messageNewService");
		userModel = (UserModel) ctx.getBean("userModel");
		authHelper = (AuthHelper) ctx.getBean("authHelper");
		templateMessageTransferHelper = (TemplateMessageTransferHelper) ctx.getBean("templateMessageTransferHelper");
//		coolAppFeignClient = (CoolAppFeignClient) ctx.getBean("coolAppFeignClient");
		try {
			LOG.info(DateUtil.getString() + " loopView start");
			loopView(0,0);
		} catch (Exception e) {
			LOG.error("loopView 启动失败", e);
		}
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		try {
			LOG.info(DateUtil.getString() + " loopView over");
			loopClose();
		} catch (Exception e) {
			LOG.error("loopView 停止失败", e);
		}
	}

	/**
	 * 轮询推送表
	 * @param saleAndPayment 是否销售简报、未回款提醒
	 * @param pushTime		推送时间
	 * @author chy
	 * @date  2016-12-6 上午11:00:33
	 */
	private void loopView(final Integer saleAndPayment, final Integer pushTime){
		Runnable runnable = () -> {
            //退回公海池推送
            LOG.info(DateUtil.getString()+"customer back public loopViewing");
            Integer now = DateUtil.getInt();
            //今天的推送
            Integer startPushTime = DateUtil.getTodayInt() - 60;
            Integer endPushTime = now + 30;
            LOG.info(DateUtil.getString() + " saleAndPayment:"+saleAndPayment+" pushTime:"+pushTime);
            Map<String,Object> param = new HashMap<>(16);

            if (pushTime > 0) {
                LOG.info(DateUtil.getString() + " pushTime:"+ DateUtil.getString(DateUtil.getTodayInt() + pushTime));
                param.put("pushTime", DateUtil.getTodayInt() + pushTime);
            } else {
                param.put("startPushTime", startPushTime);
                param.put("endPushTime", endPushTime);
            }

            param.put("isPush", 0);
            param.put("SFA", 0);
            param.put("type", PushTypeLevelEnum.CUSTOMER_BACK_PUSH.getType());
            param.put("del", 0);
            param.put("start", 0);
            param.put("pageNum", 500);
            List<PushEntity> pushList;
            try {
                pushList = pushModel.findEntitys(param);
            } catch (Exception e) {
                pushList = new ArrayList<>();
                LOG.error("轮询tb_push时错误", e);
            }

            LOG.info(DateUtil.getString() + " param:"+param);
            LOG.info(DateUtil.getString() + "cusomter public pushList.size:"+pushList.size());
			pushNewMessageList(pushList);
        };

		Runnable runnable1 = () -> {
            //sfa推送
            LOG.info(DateUtil.getString()+" sfa loop Viewing");
            Integer now = DateUtil.getInt();
            Integer startPushTime = DateUtil.getTodayInt() - 60;
            Integer endPushTime = now + 30;
            LOG.info(DateUtil.getString() + " saleAndPayment:"+saleAndPayment+" pushTime:"+pushTime);
            Map<String,Object> param = new HashMap<>(16);

            if(pushTime > 0){
                LOG.info(DateUtil.getString() + " pushTime:"+ DateUtil.getString(DateUtil.getTodayInt() + pushTime));
                param.put("pushTime", DateUtil.getTodayInt() + pushTime);
            }else{
                param.put("startPushTime", startPushTime);
                param.put("endPushTime", endPushTime);
            }
            List<Integer> typeIn = new ArrayList<>();
			typeIn.add(PushTypeEnum.WORKFLOW_SEND_MESSAGE.getCode());
			typeIn.add(PushTypeEnum.SFA_PUSH.getCode());

            param.put("isPush", 0);
            param.put("del", 0);
            param.put("typeIn", typeIn);
			param.put("start", 0);
			param.put("pageNum", 500);
            List<PushEntity> pushList;
            try {
                pushList = pushModel.findEntitys(param);
            } catch (Exception e) {
                pushList = new ArrayList<>();
                LOG.error("轮询tb_push时错误", e);
            }

            LOG.info(DateUtil.getString() + " param:"+param);
            LOG.info(DateUtil.getString() + "sfa pushList.size:"+pushList.size());
			pushNewMessageList(pushList);
        };

		Runnable runnable2 = () -> {
            //客户模块单独提出(除sfa推送的客户数据)
            LOG.info(DateUtil.getString()+"loop2 Viewing");
            Integer now = DateUtil.getInt();
            Integer startPushTime = DateUtil.getTodayInt() - 60;
            Integer endPushTime = now + 30;
            LOG.info(DateUtil.getString() + " saleAndPayment:"+saleAndPayment+" pushTime:"+pushTime);
            Map<String,Object> param = new HashMap<>(16);

            if(pushTime > 0){
                LOG.info(DateUtil.getString() + " pushTime:"+ DateUtil.getString(DateUtil.getTodayInt() + pushTime));
                param.put("pushTime", DateUtil.getTodayInt() + pushTime);
            }else{
                param.put("startPushTime", startPushTime);
                param.put("endPushTime", endPushTime);
            }

            param.put("isPush", 0);
            param.put("del", 0);
            param.put("SFA", 0);
			param.put("start", 0);
			param.put("pageNum", 500);
            param.put("type", PushTypeLevelEnum.CUSTOMER_PUSH.getType());
            List<PushEntity> pushList;
            try {
                pushList = pushModel.findEntitys(param);
            } catch (Exception e) {
                pushList = new ArrayList<>();
                LOG.error("轮询tb_push时错误", e);
            }
            LOG.info(DateUtil.getString() + " param:"+param);
            LOG.info(DateUtil.getString() + "customer pushList.size:"+pushList.size());
			pushNewMessageList(pushList);
        };

		Runnable runnable3 = () -> {
            //level = 1的
            LOG.info(DateUtil.getString()+"loop3 Viewing");
            Integer now = DateUtil.getInt();
            Integer startPushTime = DateUtil.getTodayInt() - 60;
            Integer endPushTime = now + 30;
            LOG.info(DateUtil.getString() + " saleAndPayment:"+saleAndPayment+" pushTime:"+pushTime);
            Map<String,Object> param = new HashMap<>(16);

            if(pushTime > 0){
                LOG.info(DateUtil.getString() + " pushTime:"+ DateUtil.getString(DateUtil.getTodayInt() + pushTime));
                param.put("pushTime", DateUtil.getTodayInt() + pushTime);
            }else{
                param.put("startPushTime", startPushTime);
                param.put("endPushTime", endPushTime);
            }

            param.put("isPush", 0);
            param.put("del", 0);
            param.put("SFA", 0);
            Set<Integer> typeIn = new HashSet<>();
            typeIn.add(PushTypeLevelEnum.COMMUNICATE_PLAN_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.COMMUNICATE_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.CONTRACT_REMIND.getType());
            typeIn.add(PushTypeLevelEnum.APPROVAL_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.WORKORDER_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.EXPIRED_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.EXPORT_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.EXPORT_PUSH_FAIL.getType());
			typeIn.add(PushTypeLevelEnum.PAYMENT_TASK_PUSH.getType());
            param.put("typeIn", typeIn);
			param.put("start", 0);
			param.put("pageNum", 500);
            List<PushEntity> pushList;
            try {
                pushList = pushModel.findEntitys(param);
            } catch (Exception e) {
                pushList = new ArrayList<>();
                LOG.error("轮询tb_push时错误", e);
            }
            LOG.info(DateUtil.getString() + " param:"+param);
            LOG.info(DateUtil.getString() + "level1 pushList.size:"+pushList.size());
			pushNewMessageList(pushList);
		};

		Runnable runnable4 = () -> {
            //level = 2的
            LOG.info(DateUtil.getString()+"loop4 Viewing");
            Integer now = DateUtil.getInt();
            Integer startPushTime = DateUtil.getTodayInt() - 60;
            Integer endPushTime = now + 30;
            LOG.info(DateUtil.getString() + " saleAndPayment:"+saleAndPayment+" pushTime:"+pushTime);
            Map<String,Object> param = new HashMap<>(16);

            if(pushTime > 0){
                LOG.info(DateUtil.getString() + " pushTime:"+ DateUtil.getString(DateUtil.getTodayInt() + pushTime));
                param.put("pushTime", DateUtil.getTodayInt() + pushTime);
            }else{
                param.put("startPushTime", startPushTime);
                param.put("endPushTime", endPushTime);
            }

            param.put("isPush", 0);
            param.put("del", 0);
            param.put("SFA", 0);
            Set<Integer> typeIn = new HashSet<>();
            typeIn.add(PushTypeLevelEnum.CUSTOMER_REMIND.getType());
			typeIn.add(PushTypeLevelEnum.CLUE_REMIND.getType());
			typeIn.add(PushTypeLevelEnum.CLUE_WILL_BACK_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.SALE_REPORT_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.PAYMENT_REMIND.getType());
            typeIn.add(PushTypeLevelEnum.PAYMENT_PLAN_ADD_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.PAYMENT_SHEET_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAYMENT_SHEET_BAD_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAYMENT_SHEET_RED_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAYMENT_SHEET_PREPAYMENT_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAYMENT_SHEET_RED_PREPAYMENT_ADD_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.PAYMENT_OVERDUE_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.QUOTATION_REMIND.getType());
            typeIn.add(PushTypeLevelEnum.PAY_PLAN_ADD_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.PAY_PLAN_REMIND.getType());
            typeIn.add(PushTypeLevelEnum.PAY_PLAN_OVERDUE_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAY_SHEET_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAY_SHEET_BAD_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAY_SHEET_RED_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAY_SHEET_PREPAY_ADD_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.PAY_SHEET_RED_PREPAY_ADD_PUSH.getType());
            param.put("typeIn", typeIn);
			param.put("start", 0);
			param.put("pageNum", 500);
            List<PushEntity> pushList;
            try {
                pushList = pushModel.findEntitys(param);
            } catch (Exception e) {
                pushList = new ArrayList<>();
                LOG.error("轮询tb_push时错误", e);
            }
            LOG.info(DateUtil.getString() + " param:"+param);
            LOG.info(DateUtil.getString() + "level2 pushList.size:"+pushList.size());
			pushNewMessageList(pushList);
        };

		Runnable runnable5 = () -> {
            //level = 3的
            LOG.info(DateUtil.getString()+"loop5 Viewing");
            Integer now = DateUtil.getInt();
            Integer startPushTime = DateUtil.getTodayInt() - 60;
            Integer endPushTime = now + 30;
            LOG.info(DateUtil.getString() + " saleAndPayment:"+saleAndPayment+" pushTime:"+pushTime);
            Map<String,Object> param = new HashMap<>(16);

            if(pushTime > 0){
                LOG.info(DateUtil.getString() + " pushTime:"+ DateUtil.getString(DateUtil.getTodayInt() + pushTime));
                param.put("pushTime", DateUtil.getTodayInt() + pushTime);
            }else{
                param.put("startPushTime", startPushTime);
                param.put("endPushTime", endPushTime);
            }

            param.put("isPush", 0);
            param.put("del", 0);
            param.put("SFA", 0);
            Set<Integer> typeIn = new HashSet<>();
            typeIn.add(PushTypeLevelEnum.OPPORTUNITY_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.CONTRACT_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.WORK_REPORT_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.CONTACT_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.CUSTOMER_STAGE.getType());
            typeIn.add(PushTypeLevelEnum.PURCHASE_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.INSTOCK_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.OUTSTOCK_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.SUPPLIER_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.INVOICE_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.INVOICE_RED_ADD_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.SIGN_IN_ADD_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.BOMBILL_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.PRODUCTION_ORDER_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.QUOTATION_PUSH.getType());
            typeIn.add(PushTypeLevelEnum.DATA_WARNING_PUSH.getType());
			typeIn.add(PushTypeLevelEnum.DISTRIBUTOR_CONTACT_PUSH.getType());
            param.put("typeIn", typeIn);
param.put("start", 0);
param.put("pageNum", 500);
            List<PushEntity> pushList;
            try {
                pushList = pushModel.findEntitys(param);
            } catch (Exception e) {
                pushList = new ArrayList<>();
                LOG.error("轮询tb_push时错误", e);
            }
            LOG.info(DateUtil.getString() + " param:"+param);
            LOG.info(DateUtil.getString() + "level3 pushList.size:"+pushList.size());
			pushNewMessageList(pushList);
        };

		if (executorLoop1 == null || executorLoop1.isShutdown() || executorLoop1.isTerminated()) {
			executorLoop1 = Executors.newScheduledThreadPool(1);
			LOG.info(DateUtil.getString() + "sfa loop start");
			executorLoop1.scheduleWithFixedDelay(runnable1,0, 5000, TimeUnit.MILLISECONDS);
		}
		if (executorLoop2 == null || executorLoop2.isShutdown() || executorLoop2.isTerminated()) {
			executorLoop2 = Executors.newScheduledThreadPool(3);
			LOG.info(DateUtil.getString() + "customer loop2 start");
			executorLoop2.scheduleWithFixedDelay(runnable2, 0, 5000, TimeUnit.MILLISECONDS);
		}
		if (executorLoop3 == null || executorLoop3.isShutdown() || executorLoop3.isTerminated()) {
			executorLoop3 = Executors.newScheduledThreadPool(3);
			LOG.info(DateUtil.getString() + "level1 loop3 start");
			executorLoop3.scheduleWithFixedDelay(runnable3, 0 ,5000, TimeUnit.MILLISECONDS);
		}
		if (executorLoop4 == null || executorLoop4.isShutdown() || executorLoop4.isTerminated()) {
			executorLoop4 = Executors.newScheduledThreadPool(1);
			LOG.info(DateUtil.getString() + "level2 loop4 start");
			executorLoop4.scheduleWithFixedDelay(runnable4, 0 ,5000, TimeUnit.MILLISECONDS);
		}
		if (executorLoop5 == null || executorLoop5.isShutdown() || executorLoop5.isTerminated()) {
			executorLoop5 = Executors.newScheduledThreadPool(1);
			LOG.info(DateUtil.getString() + "level3 loop5 start");
			executorLoop5.scheduleWithFixedDelay(runnable5, 0 ,5000, TimeUnit.MILLISECONDS);
		}
		if (executorLoop6 == null || executorLoop6.isShutdown() || executorLoop6.isTerminated()) {
			executorLoop6 = Executors.newScheduledThreadPool(1);
			LOG.info(DateUtil.getString() + "customer back public loop start");
			executorLoop6.scheduleWithFixedDelay(runnable, 0, 5000, TimeUnit.MILLISECONDS);
		}
	}

	/**
	 * 关闭轮询
	 * @throws Exception e
	 * @author chy
	 * @date 2016-12-6 上午10:59:50
	 */
	private void loopClose() throws Exception {
		LOG.info(DateUtil.getString() + " loopClose");
		LOG.info("loop close");
		if (executorLoop != null) {
			executorLoop.shutdown();
			executorLoop = null;
		}
		executorLoop1.shutdown();
		executorLoop1 = null;
		executorLoop2.shutdown();
		executorLoop2 = null;
		executorLoop3.shutdown();
		executorLoop3 = null;
		executorLoop4.shutdown();
		executorLoop4 = null;
		executorLoop5.shutdown();
		executorLoop5 = null;
	}

	/**
	 * 信息推送
	 * @param corpid 公司id
	 * @param message 消息
	 * @param userIdList 推送对象
	 * @author chy
	 * @date  2016-12-6 上午11:00:10
	 */
	private Map<String, Object> push(String corpid, AbstractMessage message, List<String> userIdList) throws OApiException {
		Map<String,Object> retMap = new HashMap<>(16);
		String accessToken;
		String agentId;
		try {
			accessToken = authHelper.getAccessToken(corpid);
			agentId = authHelper.getAgentId(corpid, Env.DING_XBB_APP_ID);
		} catch(Exception e) {
			LOG.error("获取accessToken或agentId失败", e);
			retMap.put("errorcode", 3);//这里注意用的是与钉钉一致的错误码字段，即errcode，kafka统一http用的钉钉的帮助类
			retMap.put("msg", "获取accessToken或agentId失败");
			return retMap;
		}
		for(String userId : userIdList){
			LightAppMessageDelivery lightAppMessageDelivery = new LightAppMessageDelivery(userId, "", agentId);
			lightAppMessageDelivery.withMessage(message);
			//推送信息
			try {
				MessageHelper.send(accessToken, lightAppMessageDelivery);
			} catch (OApiException e) {
				LOG.error("推送失败", e);
				retMap.put("errorcode", 3);
				retMap.put("msg", "推送失败");
				//推送失败的情况下把corpid入redis,下次推送如果有该corpid则不推送(ps:效率太低弃用)
//				JedisUtils.setValue(MessagePushConstant.PUSH_MESSAGE_FAIL, corpid, MessagePushConstant.PUSH_FAIL_TRUE, 60);
//				return retMap;
				throw e;
			} catch (Exception e) {
				LOG.error("非钉钉接口错误，可能是socket错误:",e);
				retMap.put("errorcode", 3);
				retMap.put("msg", "推送失败");
				return retMap;
			}

		}
		retMap.put("errorcode", 1);
		retMap.put("msg", "推送成功");
		return retMap;
	}

	private void pushNewMessageList(List<PushEntity> pushEntityList) {
		Set<String> failCorpidList = new HashSet<>();
		for (PushEntity pushEntity : pushEntityList) {
			if (failCorpidList.contains(pushEntity.getCorpid())) {
				continue;
			}

			OA oaMessage = JSONObject.parseObject(pushEntity.getMsg(), OA.class);

			List<String> userIdList;
			try {
				userIdList = JSONObject.parseArray(pushEntity.getPushObject(), String.class);
			} catch (Exception e) {
				LOG.error("pushObject类型转换错误", e);
				continue ;
			}

			if (userIdList == null || userIdList.size() < 1) {
				/*
				user表查不到对应记录可能说明消息实体内pushObject字段为空或空数组
				以上情况下该条推送消息都是无效的，所以将对应的消息del置为2，表示无用消息
				避免影响下次轮询
				 */
				pushEntity.setDel(2);
				try {
					pushModel.save(pushEntity);
				} catch (Exception e) {
					LOG.error("数据库操作失败", e);
					continue;
				}
				continue;
			}

			String dingtalkUserIdStr = null;
			List<UserEntity> userList;
			try {
				userList = userModel.getByUserIdIn(pushEntity.getCorpid(), userIdList, true);
			} catch (Exception e) {
				LOG.error("查询数据库出错", e);
				continue;
			}
			if (userList == null || userIdList.size() == 0) {
				/*
				user表查不到对应记录可能有三种情况
				1.该user不存在
				2.该user已离职
				3.该user不在可见范围内
				以上情况下该条推送消息都是无效的，所以将对应的消息del置为2，表示无用消息
				避免影响下次轮询
				 */
				pushEntity.setDel(2);
				try {
					pushModel.save(pushEntity);
				} catch (Exception e) {
					LOG.error("数据库操作失败", e);
					continue;
				}
				continue;
			}
			for (UserEntity user : userList) {
				if (!user.getCorpid().startsWith("xbb")) {
					if (dingtalkUserIdStr == null) {
						dingtalkUserIdStr = user.getUserId();
					} else {
						dingtalkUserIdStr += "," + user.getUserId();
					}
				}
			}


			CorpConversationHelper.SendByTemplateResponse response;
			if (pushEntity.getCorpid() != null && pushEntity.getCorpid().startsWith("ding")) {
				try {
					if (dingtalkUserIdStr != null && dingtalkUserIdStr.length() > 0) {

						TemplateMessage templateMessage = templateMessageTransferHelper.transferToTemplateMessage(oaMessage);

						response = messageNewService.dingtalkWorkMessageByTemplatePushToUserAndDept(pushEntity.getCorpid(), templateMessage, dingtalkUserIdStr, null);
						if (response != null) {
							pushEntity.setTaskId(response.getTaskId());
							if (response.getErrcode() == null || response.getErrcode() != 0){
								LOG.error("SysContextListener.pushNewMessageList error: response: " + JSON.toJSONString(response));
							}
						}else {
							LOG.error("SysContextListener.pushNewMessageList error: response is null");
						}
						pushEntity.setIsPush(1);
					} else {
						//推送对象没有直接标记无效消息，用del=2标记
						pushEntity.setDel(2);
					}
				} catch (XbbException e) {
					//获取accessToken或agentId失败,企业不存在或者以及被解散，用del=3标记
					pushEntity.setDel(3);
					failCorpidList.add(pushEntity.getCorpid());
				} catch (Exception e) {
					LOG.error("Exception e=============" ,e );
				}

				try {
					pushModel.save(pushEntity);
				} catch (Exception e) {
					LOG.error("数据库操作失败", e);
					continue;
				}

				try {
					// 钉钉平台特性
					if ((Objects.equals(pushEntity.getRefEntity(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()) || Objects.equals(pushEntity.getRefEntity(), XbbRefTypeEnum.COMMUNICATE_PLAN.getCode()))
							&& Objects.equals(pushEntity.getIsRemind(), BasicConstant.ONE)) {
						UserVO userVO = new UserVO();
						userVO.setCorpid(pushEntity.getCorpid());
						userVO.setUserId(userList.get(0).getUserId());
						userVO.setName(userList.get(0).getName());
						CoolAppSendRemindTopCardDTO coolAppSendRemindTopCardDTO = new CoolAppSendRemindTopCardDTO(pushEntity.getCorpid(), userVO, PlatFormEnum.INTERNAL.getValue(),
								pushEntity.getRefId(), pushEntity.getType(), pushEntity.getPushObject(), pushEntity.getMsg(), pushEntity.getPushTime());
						if (Objects.equals(pushEntity.getRefEntity(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
							coolAppFeignClient.sendCommunicateTopCard(coolAppSendRemindTopCardDTO, LocaleContextHolder.getLocale().toString());
						} else {
							coolAppFeignClient.sendCommunicatePlanTopCard(coolAppSendRemindTopCardDTO, LocaleContextHolder.getLocale().toString());
						}
					}
				} catch (Exception e) {
					LOG.error("调用失败：coolAppFeignClient.sendCommunicateTopCard || sendCommunicatePlanTopCard ",e);
				}
			}
		}
		/*Set<String> failCorpidList = new HashSet<>();
		for (PushEntity pushEntity : pushEntityList) {
			if (failCorpidList.contains(pushEntity.getCorpid())) {
				continue;
			}
			JSONObject messageObject;
			try {
				messageObject = JSONObject.parseObject(pushEntity.getMsg());
			} catch (Exception e) {
				LOG.error("messageObject类型转换错误", e);
				continue ;
			}

			//消息体封装
			OA oa = new OA();

			OA.Body body = new OA.Body();
			body.setTitle(messageObject.getString("title"));
			body.setContent(messageObject.getString("content"));

			String messageUrl = messageObject.getString("messageUrl");
			//下载不需要添加&ov=y&corpid=
			if (!(messageObject.getString("messageUrl")!=null && messageObject.getString("messageUrl").contains(".xls"))) {
				messageUrl += "&ov=y&corpid=" + pushEntity.getCorpid() + "&appid=" + Env.DING_XBB_APP_ID;
			}
			oa.setMessageUrl(messageUrl);
			String pcMessageUrl = messageObject.getString("pcMessageUrl");
			if (!StringUtil.isEmpty(pcMessageUrl)) {
				if (!(messageObject.getString("pcMessageUrl")!=null && messageObject.getString("pcMessageUrl").contains(".xls"))) {
					pcMessageUrl += "&ov=y&corpid=" + pushEntity.getCorpid() + "&appid=" + Env.DING_XBB_APP_ID;
				}

				//remove messageObject中的对应字段
				messageObject.remove("pcMessageUrl");
				//移除销售简报内的无用start和end
				messageObject.remove("content");
				messageObject.remove("start");
				messageObject.remove("end");
			}
			oa.setPcMessageUrl(pcMessageUrl);

			//remove messageObject中的对应字段
			messageObject.remove("content");
			messageObject.remove("messageUrl");
			//移除下载链接
			messageObject.remove("downLoadUrl");

			List<OA.Body.Form> form = new ArrayList<>();
			Set<Map.Entry<String, Object>> set = messageObject.entrySet();
			for (Map.Entry<String, Object> entry : set) {
				String key = entry.getKey();
				Object value = entry.getValue();
				OA.Body.Form f = new OA.Body.Form();
				if(!key.equals("text") && !key.equals("title")){
					f.setKey(key);
					f.setValue(value.toString());
					form.add(f);
				}
			}

			body.setForm(form);
			body.setAuthor("销帮帮CRM");
			oa.setBody(body);
			//封装结束

			List<String> userIdList;
			try {
				userIdList = JSONObject.parseArray(pushEntity.getPushObject(), String.class);
			} catch (Exception e) {
				LOG.error("pushObject类型转换错误", e);
				continue ;
			}

			if (userIdList == null || userIdList.size() < 1) {
				*//*
				user表查不到对应记录可能说明消息实体内pushObject字段为空或空数组
				以上情况下该条推送消息都是无效的，所以将对应的消息del置为2，表示无用消息
				避免影响下次轮询
				 *//*
				pushEntity.setDel(2);
				try {
					pushModel.save(pushEntity);
				} catch (Exception e) {
					LOG.error("数据库操作失败", e);
					continue;
				}
				continue;
			}

			String dingtalkUserIdStr = null;
			List<UserEntity> userList;
			try {
				userList = userModel.getByUserIdIn(pushEntity.getCorpid(), userIdList);
			} catch (Exception e) {
				LOG.error("查询数据库出错", e);
				continue;
			}
			if (userList == null || userIdList.size() == 0) {
				*//*
				user表查不到对应记录可能有三种情况
				1.该user不存在
				2.该user已离职
				3.该user不在可见范围内
				以上情况下该条推送消息都是无效的，所以将对应的消息del置为2，表示无用消息
				避免影响下次轮询
				 *//*
				pushEntity.setDel(2);
				try {
					pushModel.save(pushEntity);
				} catch (Exception e) {
					LOG.error("数据库操作失败", e);
					continue;
				}
				continue;
			}
			for (UserEntity user : userList) {
				if (!user.getCorpid().startsWith("xbb")) {
					if (dingtalkUserIdStr == null) {
						dingtalkUserIdStr = user.getUserId();
					} else {
						dingtalkUserIdStr += "," + user.getUserId();
					}
				}
			}


			CorpConversationHelper.SendResponse response;
			if (pushEntity.getCorpid() != null && pushEntity.getCorpid().startsWith("ding")) {
				try {
					if (dingtalkUserIdStr != null && dingtalkUserIdStr.length() > 0) {
						response = messageNewService.dingtalkOAMessagePushToUserAndDept(pushEntity.getCorpid(), oa, dingtalkUserIdStr, null);
						if (response != null) {
							pushEntity.setTaskId(response.getTaskId());
						}
						pushEntity.setIsPush(1);
					} else {
						//推送对象没有直接标记无效消息，用del=2标记
						pushEntity.setDel(2);
					}
				} catch (XbbException e) {
					//获取accessToken或agentId失败,企业不存在或者以及被解散，用del=3标记
					pushEntity.setDel(3);
					failCorpidList.add(pushEntity.getCorpid());
				} catch (Exception e) {
					LOG.error("Exception e=============" ,e );
				}

				try {
					pushModel.save(pushEntity);
				} catch (Exception e) {
					LOG.error("数据库操作失败", e);
					continue;
				}

			}

		}*/

	}
}